package com.example.demo.serviceImpl.task;

import com.example.demo.po.user.User;
import com.example.demo.service.task.RecommendService;
import com.example.demo.service.task.TaskService;
import com.example.demo.service.user.UserService;
import com.example.demo.utils.Constant;
import com.example.demo.utils.UserHolder;
import com.example.demo.vo.ResultVO;
import com.example.demo.vo.user.WorkerTaskVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Service
public class RecommendServiceImpl implements RecommendService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Resource
    UserService userService;

    @Resource
    TaskService taskService;

    private static final ExecutorService RECOMMEND_EXECUTOR = Executors.newFixedThreadPool(10);

    private final BlockingQueue<Info> recommendQueue = new ArrayBlockingQueue<>(1024 * 512);

    private class StartRecommend implements Runnable{

        @Override
        public void run() {
            while (true){
                try {
                    // 1.获取队列中信息
                    Info info=recommendQueue.take();
                    int tid= info.tid;
                    int strategy=info.strategy;
                    // 2.执行算法
                    List<User> users=null;
                    switch (strategy){
                        case Constant.RECOMMEND_WITH_EXP:
                            users=taskService.recommendByExp(tid);
                            break;
                        case Constant.RECOMMEND_WITH_SIM:
                            users=taskService.recommendByRel(tid);
                            break;
                        case Constant.RECOMMEND_WITH_DIV:
                            users=taskService.recommendByDiversity(tid);
                            break;
                        case Constant.RECOMMEND_WITH_COMPREHENSIVE:
                            users=taskService.recommendAll(tid);
                            break;
                        default:
                            return;
                    }
                    if(users==null){
                        return;
                    }
                    for(User user:users){
                        String key= Constant.RECOMMEND_FOR_WORKER_TOKEN+user.getUid();
                        stringRedisTemplate.opsForSet().add(key,String.valueOf(tid));
                    }
                } catch (Exception e) {
                    System.out.println("异步推荐异常");
                }
            }
        }
    }
    private static class Info{
        int tid;
        int strategy;

        public Info(){};

        public Info(int tid, int strategy) {
            this.tid = tid;
            this.strategy = strategy;
        }
    }

    @PostConstruct
    private void init() {
        RECOMMEND_EXECUTOR.submit(new StartRecommend());
    }

    @Override
    public ResultVO<Integer> getUsersToRecommend(int tid,int strategy) {
        Info info= new Info(tid, strategy);
        recommendQueue.offer(info);
//        List<User> users=null;
//        switch (strategy){
//            case Constant.RECOMMEND_WITH_EXP:
//                users=taskService.recommendByExp(tid);
//                break;
//            case Constant.RECOMMEND_WITH_SIM:
//                users=taskService.recommendByRel(tid);
//                break;
//            case Constant.RECOMMEND_WITH_DIV:
//                users=taskService.recommendByDiversity(tid);
//                break;
//            case Constant.RECOMMEND_WITH_COMPREHENSIVE:
//                break;
//            default:
//                return new ResultVO<>(-1,"没有该类型策略",0);
//        }
//        if(users==null){
//            return new ResultVO<>(-1,"没有该类型策略",0);
//        }
//        int count=users.size();
//        for(User user:users){
//            String key= Constant.RECOMMEND_FOR_WORKER_TOKEN+user.getUid();
//            stringRedisTemplate.opsForSet().add(key,String.valueOf(tid));
//        }

        return new ResultVO<>(1,"成功",10);
    }

    @Override
    public ResultVO<List<Integer>> getMyRecommend() {
        if(UserHolder.getUser()==null)
            return new ResultVO<>(-1,"用户验证失败",Collections.emptyList());
        int uid= UserHolder.getUser().getUid();
        String key= Constant.RECOMMEND_FOR_WORKER_TOKEN+uid;
        Set<String> members = stringRedisTemplate.opsForSet().members(key);
        if(members==null||members.isEmpty()){
            return new ResultVO<>(1,"没有推荐", Collections.emptyList());
        }
        List<Integer> res=new ArrayList<>();
        for(String s:members){
            ResultVO<WorkerTaskVO> takeTaskState = userService.getTakeTaskState(UserHolder.getUser().getUsername(), Integer.parseInt(s));
            if(takeTaskState.getData().getTakeState()==2||takeTaskState.getData().getTakeState()==3)
                continue;
            res.add(Integer.parseInt(s));
        }
        return new ResultVO<>(1,"成功",res);

    }

    @Override
    public ResultVO<List<Integer>> ignoreRecommend(int tid) {
        if(UserHolder.getUser()==null)
            return new ResultVO<>(-1,"用户验证失败",Collections.emptyList());
        int uid= UserHolder.getUser().getUid();
        String key= Constant.RECOMMEND_FOR_WORKER_TOKEN+uid;
        Long remove = stringRedisTemplate.opsForSet().remove(key, String.valueOf(tid));
        return getMyRecommend();

    }
}
